/*
 * 简述：主要对数字，字符串等得处理
 * 详述：工具类，提供对字符串为空，是否为数字等判断
 * @Copyright: Yisin (c) 2016
 * 修改人：Yisin
 * 版本：1.0
 */

package com.yinsin.jpabatis.util;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.regex.Matcher;

/**
 * 简述:该类是工具类，提供对字符串，数字等的操作 详述:主要提供了以下几个特性(可以继续扩展):
 * <ul>
 * <li>判断字符是否为数字</li>
 * <li>字符串是否是数字串</li>
 * <li>字符是否是小写</li>
 * <li>字符串是否是小写字符</li>
 * <li>字符是否是大写字符</li>
 * <li>字符串是否是大写字符串</li>
 * <li>int值转换为十六进制</li>
 * <li>long值转换为十六进制</li>
 * <li>int值转换为八进制</li>
 * <li>long值转换为八进制</li>
 * <li>int值转换为二进制</li>
 * <li>long值转换为二进制</li>
 * <li>判断对象是否为空</li>
 * <li>判断空对象是否不为空</li>
 * <li>判断字符串是否为空字符串</li>
 * <li>判断字符串是否不为空字符串</li>
 * <li>处理Null或空字符串</li>
 * <li>处理Null或空对象</li>
 * <li>汉字字符编码转换</li>
 * <li>字符串转换成UTF-8字符串</li>
 * <li>字符串转换成GBK字符串</li>
 * <li>验证手机号是否正确</li>
 * <li>验证邮箱是否正确</li>
 * <li>获取ByteArrayOutputStream字节，并转换成字符串,默认使用UTF-8字符集</li>
 * <li>获取ByteArrayOutputStream字节，并转换成字符串</li>
 * <li>将Object类型转换为String类型</li>
 * <li>将Object类型转换为int类型</li>
 * <li>将Object类型转换为long类型</li>
 * <li>将Object类型转换为float类型</li>
 * <li>将Object类型转换为double类型</li>
 * <li>将String类型转换为int类型</li>
 * <li>将String类型转换为long类型</li>
 * <li>将String类型转换为float类型</li>
 * <li>将String类型转换为double类型</li>
 * <li>获取指定长度的随机数字字符串</li>
 * <li>获取UUID字符串（去除了-）</li>
 * <li>将第1个字母转换为大写</li>
 * <li>将第1个字母转换为小写</li>
 * <li>将Unicode编码转换为正常字符</li>
 * <li>将字符转换为Unicode编码</li>
 * <li>字符串格式化 format</li>
 * <li>获取时间戳（Unix）</li>
 * <li>过滤html标签</li>
 * <li>数值四舍五入 round</li>
 * <li>是否为有效自然数，即>0的数，主要用于主键值判断</li>
 * </ul>
 * 
 * @author Yisin
 * @version 1.0
 */
public final class CommonUtils {

    private CommonUtils() {
    }

    /**
     * 判断字符是否是数字
     * 
     * @author Yisin
     * 
     * @param sch 字符
     * @return boolean true:字符是数字 false:字符不是数字
     */
    public static boolean isDigit(final char sch) {
        final int temp = sch & 255;
        return temp >= 45 && temp <= 57;
    }

    /**
     * 字符串是否是数字串
     * 
     * @author Yisin
     * @param string
     *            字符串
     * @return boolean true:数字 false：非数字
     */
    public static boolean isDigit(final String string) {
        boolean digit = false;
        if (CommonUtils.isNotBlank(string)) {
            digit = Constants.REG_INTEGER.matcher(string).matches();
        }
        return digit;
    }

    /**
     * 字符是否是小写,只能包含a-z字符，不能包含特殊字符
     * 
     * @author Yisin
     * 
     * @param sch 字符
     * @return boolean true:小写字符
     */
    public static boolean isLowerCase(final char sch) {
        final int temp = sch & 255;
        return temp >= 97 && temp <= 122;
    }

    /**
     * 字符串是否是小写字符
     * 
     * @author Yisin
     * 
     * @param string
     *            字符串
     * @return boolean true:字符串为小写字符串
     */
    public static boolean isLowerCase(final String string) {
        return isNotBlank(string) ? Constants.REG_IS_LOWCASE.matcher(string).matches() : false;
    }

    /**
     * 字符是否是大写字符
     * 
     * @author Yisin
     * 
     * @param sch 字符
     * @return boolean true:大写字符
     */
    public static boolean isUppercase(final char sch) {
        final int temp = sch & 255;
        return temp >= 65 && temp <= 90;
    }

    /**
     * 字符串是否是大写字符串
     * 
     * @author Yisin
     * @param string
     *            字符串
     * @return boolean true:字符串为大写字符串
     */
    public static boolean isUppercases(final String string) {
        return isNotBlank(string) ? Constants.REG_IS_UPPERCASE.matcher(string).matches() : false;
    }

    /**
     * 将字符串转换成hexstring
     * 
     * @author Yisin
     * 
     * @param sourceStr
     *            需要转换的字符串
     * @return String 转换后的字符串
     */
    public static String toHexString(final String sourceStr) {
        final StringBuffer strBuff = new StringBuffer(Constants.CHAR_EMPTY);
        if (CommonUtils.isNotBlank(sourceStr)) {
            for (char ch : sourceStr.toCharArray()) {
                strBuff.append(toHexString(ch));
            }
        }
        return strBuff.toString();
    }

    /**
     * 简述：将将字节数组转换成十六进制数字
     * 详述：字节转换，循环转换字节数组，将单个字节数组转换成十六进制字符
     * 
     * @author Yisin
     * @param bytes
     *            字节数组
     * @return String 返回转换后的字符串
     */
    public static String bytesToHexString(final byte[] bytes) {
        final StringBuilder sBuilder = new StringBuilder(Constants.CHAR_EMPTY);
        if (bytes != null && bytes.length > 0) {
            for (byte byitem : bytes) {
                final int tmpv = byitem & 0XFF;
                final String thv = Integer.toHexString(tmpv);
                if (thv.length() < 2) {
                    sBuilder.append(0);
                }
                sBuilder.append(thv);
            }
        }
        return sBuilder.toString();
    }

    private static String toUnsignedString(final long nums, final int shifts) {
        long tmpNums = nums;
        char[] chs = new char[64];
        int charPosition = 64;
        final int radix = 1 << shifts;
        final int value = radix - 1;
        do {
            chs[--charPosition] = Constants.CHAR_ARRAY[(int) (tmpNums & value)];
            tmpNums >>>= shifts;
        } while (0 < tmpNums);
        return new String(chs, charPosition, 64 - charPosition);
    }

    /**
     * int值转换为十六进制
     * @author Yisin
     * @param nums
     * @return String 十六进制字符串
     */
    public static String toHexString(final int nums) {
        return toUnsignedString(nums, 4);
    }

    /**
     * long值转换为十六进制
     * 
     * @author Yisin
     * 
     * @param nums
     * @return String 十六进制字符串
     */
    public static String toHexString(final long nums) {
        return toUnsignedString(nums, 4);
    }

    /**
     * int值转换为八进制
     * 
     * @author Yisin
     * 
     * @param nums
     * @return String 八进制字符串
     */
    public static String toOctalString(final int nums) {
        return toUnsignedString(nums, 3);
    }

    /**
     * long值转换为八进制
     * 
     * @author Yisin
     * 
     * @param nums long值
     * @return String 八进制字符串
     */
    public static String toOctalString(final long nums) {
        return toUnsignedString(nums, 3);
    }

    /**
     * int值转换为二进制
     * 
     * @author Yisin
     * @param nums
     * @return String 二进制字符串
     */
    public static String toBinaryString(final int nums) {
        return toUnsignedString(nums, 1);
    }

    /**
     * long值转换为二进制
     * 
     * @author Yisin
     * 
     * @param nums
     * @return String 二进制字符串
     */
    public static String toBinaryString(final long nums) {
        return toUnsignedString(nums, 1);
    }

    /**
     * <p>
     * 判断对象是否为空
     * </p>
     * 
     * @author Yisin
     * 
     * @param object
     *            源对象
     * @return boolean true:空对象 false:非空对象
     */
    public static boolean isEmpty(final Object object) {
        return null == object;
    }

    /**
     * <p>
     * 判断空对象是否不为空
     * </p>
     * 
     * @author Yisin
     * 
     * @param object
     *            源对象
     * @return boolean true:非空对象 false:空对象
     */
    public static boolean isNotEmpty(final Object object) {
        return !isEmpty(object);
    }

    /**
     * <p>
     * 判断字符串是否为空字符串
     * </p>
     * 
     * @author Yisin
     * 
     * @param string
     *            源字符串
     * @return boolean true:空字符串 false:非空字符串
     */
    public static boolean isBlank(final String string) {
        return isEmpty(string) || Constants.CHAR_EMPTY.equals(string.trim());
    }

    /**
     * <p>
     * 判断字符串是否不为空字符串
     * </p>
     * 
     * @author Yisin
     * 
     * @param string
     *            源字符串
     * @return boolean true:非空字符串 false:空字符串
     */
    public static boolean isNotBlank(final String string) {
        return isNotEmpty(string) && !Constants.CHAR_EMPTY.equals(string.trim());
    }
    
    /**
     * 是否为有效自然数，即>0的数，主要用于主键值判断
     * @param value
     * @return
     */
    public static boolean isEffective(Integer value){
    	return null != value && value > 0;
    }
    
    /**
     * 是否为有效自然数，即>0的数，主要用于主键值判断
     * @param value
     * @return
     */
    public static boolean isEffective(Long value){
    	return null != value && value > 0;
    }

    /**
     * <p>
     * 字符串转换成UTF-8字符串
     * </p>
     * 
     * @param string
     *            源字符串
     * @return
     */
    public static String toUTF8(final String string) {
        if (CommonUtils.isBlank(string)) {
            throw new IllegalArgumentException("The param can not be null.");
        }
        try {
            return new String(string.getBytes(Constants.CHARSET_UTF8), Constants.CHARSET_ISO88591);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return string;
    }

    /**
     * 字符串转换成GBK字符串
     * @param string
     * @return
     */
    public static String toGBK(final String string) {
        if (CommonUtils.isBlank(string)) {
            throw new IllegalArgumentException("The param can not be null.");
        }
        try {
            return new String(string.getBytes(Constants.CHARSET_GBK), Constants.CHARSET_ISO88591);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return string;
    }

    /**
     * 验证手机号是否正确
     * 
     * @author Yisin
     * @param mobile
     *            手机号
     * @return boolean true:正确的手机号 false:错误的手机号
     */
    public static boolean isLegalMobile(final String mobile) {
        return CommonUtils.isNotBlank(mobile) ? Constants.REG_MOBILE.matcher(mobile).find() : false;
    }

    /**
     * 验证邮箱是否正确
     * 
     * @author Yisin
     * @param mail
     *            邮件地址
     * @return boolean true:是否是正确的邮件地址 false:非法邮件地址
     */
    public static boolean isLegalMail(final String mail) {
        return isNotBlank(mail) ? Constants.REG_MAIL.matcher(mail.toUpperCase(Locale.getDefault())).find() : false;
    }

    /**
     * 获取ByteArrayOutputStream字节，并转换成字符串,默认使用UTF-8字符集
     * 
     * @param baos
     *            字节数组输出流
     * @return String 将内容转换成字符串
     * @author Yisin
     * 
     */
    public static String byteArrayStreamToString(ByteArrayOutputStream baos) {
        return byteArrayStreamToString(baos, Constants.CHARSET_UTF8);
    }

    /**
     * 获取ByteArrayOutputStream字节，并转换成字符串
     * 
     * @param baos
     *            字节数组输出流
     * @param charset
     *            字符集名称
     * @return String 将内容转换成字符串
     * @author Yisin
     */
    public static String byteArrayStreamToString(ByteArrayOutputStream baos, String charset) {
        if (null == baos) {
            throw new IllegalArgumentException("The param baos can not be null.");
        }
        try {
            return baos.toString(Constants.CHARSET_UTF8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 处理Null或空字符串
     * 
     * @author yisin
     * @param string
     * @return String
     */
    public static String excNullToString(String string) {
        return excNullToString(string, Constants.CHAR_EMPTY);
    }

    /**
     * 处理Null或空字符串
     * 
     * @author yisin
     * @param string
     * @param added
     * @return String
     */
    public static String excNullToString(String string, String added) {
        if (isEmpty(string)) {
            string = added;
        }
        return string;
    }

    /**
     * 处理Null或空对象
     * 
     * @author yisin
     * @param obj Object
     * @return Object
     */
    public static Object excNullToObject(Object obj) {
        return excNullToObject(obj, new Object());
    }

    /**
     * 处理Null或空对象
     * 
     * @author yisin
     * @param obj
     * @param added
     * @return Object
     */
    public static Object excNullToObject(Object obj, Object added) {
        if (isEmpty(obj)) {
            obj = added;
        }
        return obj;
    }

    /**
     * 将字Object转换为字符串
     * 
     * @author yisin
     * @param obj Object
     * @return
     */
    public static String objectToString(Object obj) {
        return objectToString(obj, null);
    }

    /**
     * 将字Object转换为字符串
     * 
     * @author yisin
     * @param obj
     * @param added
     * @return
     */
    public static String objectToString(Object obj, String added) {
        String result = added;
        if (obj != null) {
            result = String.valueOf(obj);
        }
        return result;
    }

    /**
     * 将字符串转换成整数类型，如果为空则转换成0
     * 
     * @author yisin
     * @param string
     * @return
     */
    public static int stringToInt(String string) {
        return stringToInt(string, 0);
    }

    /**
     * 将字符串转换成整数类型，如果为空则转换成指定值
     * 
     * @author yisin
     * @param string
     * @param added
     * @return
     */
    public static int stringToInt(String string, int added) {
        int result = 0;
        try {
            result = Integer.parseInt(string);
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将object转换成整数类型，如果为空则转换成0
     * 
     * @author yisin
     * @param obj
     * @return
     */
    public static int objectToInt(Object obj) {
        return objectToInt(obj, 0);
    }

    /**
     * 将object转换成整数类型，如果为空则转换成指定值
     * @param obj
     * @param added
     * @return
     */
    public static int objectToInt(Object obj, int added) {
        if (obj instanceof Integer) {
            return (Integer) obj;
        } else if (obj instanceof Float) {
            return ((Float) obj).intValue();
        } else if (obj instanceof Double) {
            return ((Double) obj).intValue();
        }
        return stringToInt(objectToString(obj), added);
    }

    /**
     * 将字符串转换成长整数类型，如果为空则转换成0
     * 
     * @author yisin
     * @param string
     * @return
     */
    public static long stringToLong(String string) {
        return stringToLong(string, 0);
    }

    /**
     * 将字符串转换成长整数类型，如果为空则转换成指定值
     * @param string
     * @param added
     * @return
     */
    public static long stringToLong(String string, long added) {
        long result = 0;
        try {
            result = Long.parseLong(string);
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将字符串转换成长整数类型，如果为空则转换成0
     * 
     * @author yisin
     * @param obj
     * @return
     */
    public static long objectToLong(Object obj) {
        return objectToLong(obj, 0);
    }

    /**
     * 将字符串转换成长整数类型，如果为空则转换成指定值
     * @param obj
     * @param added
     * @return
     */
    public static long objectToLong(Object obj, long added) {
        long result = 0;
        try {
            result = Long.parseLong(obj.toString());
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将字符串转换成float类型
     * 
     * @author yisin
     * @param string
     * @return float
     */
    public static float stringToFloat(String string) {
        return stringToFloat(string, 0.0f);
    }

    /**
     * 将字符串转换成float类型,如果为空则转为指定的值
     * @param string
     * @param added
     * @return float
     */
    public static float stringToFloat(String string, float added) {
        float result = 0.0f;
        try {
            result = Float.parseFloat(string);
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将字符串转换成float类型，如果为空则转换成0
     * 
     * @author yisin
     * @param obj
     * @return
     */
    public static float objectToFloat(Object obj) {
        return objectToFloat(obj, 0f);
    }

    /**
     * 将字符串转换成float类型，如果为空则转换成指定值
     * @param obj
     * @param added
     * @return
     */
    public static float objectToFloat(Object obj, float added) {
        float result = 0;
        try {
            result = Float.parseFloat(obj.toString());
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将字符串转换成double类型,如果为空则转为指定的值
     * 
     * @author yisin
     * @param string
     * @return double
     */
    public static double stringToDouble(String string) {
        return stringToDouble(string, 0.0d);
    }

    /**
     * 将字符串转换成double类型,如果为空则转为指定的值
     * 
     * @author yisin
     * @param string
     * @return double
     */
    public static double stringToDouble(String string, double added) {
        double result = 0.0d;
        try {
            result = Double.parseDouble(string);
        } catch (Exception e) {
            result = added;
        }
        return result;
    }

    /**
     * 将字符串转换成double类型，如果为空则转换成0
     * @param obj
     * @return
     */
    public static double objectToDouble(Object obj) {
        return objectToDouble(obj, 0f);
    }

    /**
     * 将字符串转换成double类型，如果为空则转换成指定值
     * 
     * @author yisin
     * @param obj
     * @param added
     * @return double
     */
    public static double objectToDouble(Object obj, double added) {
        double result = 0;
        try {
            result = Double.parseDouble(obj.toString());
        } catch (Exception e) {
            result = added;
        }
        return result;
    }
    
    public static BigDecimal objectToBigDecimal(Object obj) {
    	return objectToBigDecimal(obj, 0);
    }
    
    public static BigDecimal objectToBigDecimal(Object obj, double added) {
    	BigDecimal result = new BigDecimal(0);
        try {
            result = BigDecimal.valueOf(objectToDouble(obj, added));
        } catch (Exception e) {
            result = new BigDecimal(added);
        }
        return result;
    }

    /**
     * 将第1个字母转换为大写
     * 
     * @param content
     * @return String
     */
    public static String firstCharToUpperCase(String content) {
        if (!isEmpty(content)) {
            String tou = content.substring(0, 1);
            String wei = content.substring(1);
            content = tou.toUpperCase() + wei;
        }
        return content;
    }

    /**
     * 将第1个字母转换为小写
     * 
     * @param content
     * @return String
     */
    public static String firstCharToLowerCase(String content) {
        if (!isEmpty(content)) {
            String tou = content.substring(0, 1);
            String wei = content.substring(1);
            content = tou.toLowerCase() + wei;
        }
        return content;
    }

    /**
     * 将Unicode编码转换为正常字符
     * 
     * @author yisin
     * @param param
     * @return String
     */
    public static String stringUncode(String param) {
        if (param != null && !param.trim().equals(Constants.CHAR_EMPTY)) {
            try {
                param = URLDecoder.decode(param, Constants.CHARSET_UTF8);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return param;
    }

    /**
     * 将字符转换为Unicode编码
     * 
     * @author yisin
     * @param param
     * @return String
     */
    public static String stringEncode(String param) {
        if (param != null && !param.trim().equals(Constants.CHAR_EMPTY)) {
            try {
                param = URLEncoder.encode(param, Constants.CHARSET_UTF8);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return param;
    }

    /**
     * 字符串格式化
     * 
     * @param resource
     * @param target
     * @return String
     */
    public static String format(String resource, String... target) {
        if (resource == null) {
            throw new IllegalArgumentException("parameter is null");
        }
        if (target != null && target.length > 0) {
            for (int i = 0, k = target.length; i < k; i++) {
                resource = resource.replace("{" + i + "}", target[i]);
            }
        }
        return resource;
    }

    /**
     * 获取时间戳（Unix）
     * @return long
     */
    public static long getTimeUnix() {
        return new Date().getTime();
    }

    /**
     * 基本功能：过滤所有以"&lt;"开头以"&gt;"结尾的标签
     * 
     * @param str
     * @return String
     */
    public static String filterHtml(String str) {
        Matcher matcher = Constants.REG_HTML.matcher(str);
        StringBuffer sb = new StringBuffer();
        boolean result1 = matcher.find();
        while (result1) {
            matcher.appendReplacement(sb, Constants.CHAR_EMPTY);
            result1 = matcher.find();
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 数值四舍五入，最多保留两位小数
     * 
     * @param number
     *            数值
     * @return float 四舍五入后的数值
     */
    public static float round(float number) {
        return round(number, 2);
    }

    /**
     * 数值四舍五入，自定义保留小数位位数
     * 
     * @param number
     *            数值
     * @param len
     *            需要保留的小数位位数
     * @return 四舍五入后的数值字符串
     */
    public static float round(float number, int len) {
        return round(number, len, RoundingMode.UP);
    }
    
    /**
     * 数值四舍五入，自定义保留小数位位数
     * 
     * @param number
     *            数值
     * @param len
     *            需要保留的小数位位数
     * @return 四舍五入后的数值字符串
     */
    public static float round(float number, int len, RoundingMode mode) {
        return new BigDecimal(number).setScale(len, mode).floatValue();
    }
    
    /**
     * 数值四舍五入，自定义保留小数位位数
     * 
     * @param number
     *            数值
     * @param len
     *            需要保留的小数位位数
     * @return 四舍五入后的数值字符串
     */
    public static double round(double number, int len) {
        return round(number, len, RoundingMode.UP);
    }
    
    /**
     * 数值四舍五入，自定义保留小数位位数
     * 
     * @param number
     *            数值
     * @param len
     *            需要保留的小数位位数
     * @return 四舍五入后的数值字符串
     */
    public static double round(double number, int len, RoundingMode mode) {
        return new BigDecimal(number).setScale(len, mode).doubleValue();
    }
    
    /**
     * 获取指定长度的随机数字字符串
     * @param size
     * @return String
     */
    public static String getRandomNumber(int size){
    	String num = "";
		for (int i = 0; i < size; i++) {
			double a = Math.random() * 9;
			a = Math.ceil(a);
			int randomNum = new Double(a).intValue();
			num += randomNum;
		}
		return num;
    }
    
    /**
     * 获取UUID字符串（去除了-）
     * @return String
     */
    public static String getUUID(){
    	String uuid = UUID.randomUUID().toString();
		return uuid.replaceAll("-", "");
    }
    
    /** 格式化模版  #{key} */
    public static String parseTemplate(String content, String key, String value) {
        try {
            if (content != null) {
                content = content.replaceAll("#\\{" + key + "\\}", value);
            }
        } catch (Exception e) {
        }
        return content;
    }
    
    /**
     * 格式化模版 #{key}
     * @param content
     * @param data
     * @return
     */
    public static String parseTemplate(String content, Map<String, String> data) {
        try {
            if (content != null && data != null) {
            	for(Entry<String, String> entry : data.entrySet()){
            		content = content.replaceAll("#\\{" + entry.getKey() + "\\}", entry.getValue());
            	}
            }
        } catch (Exception e) {
        }
        return content;
    }
    
    /**
     * 删除字符串中的空格字符
     * @param str
     * @return
     */
    public static String deleteWhitespace(String str) {
		if (isEmpty(str)) {
			return str;
		}
		int sz = str.length();
		char[] chs = new char[sz];
		int count = 0;
		for (int i = 0; i < sz; ++i) {
			if (!(Character.isWhitespace(str.charAt(i)))) {
				chs[(count++)] = str.charAt(i);
			}
		}
		if (count == sz) {
			return str;
		}
		return new String(chs, 0, count);
	}
    
}
